package myutil

import (
	"sync"
)

// BlockQueue 并发安全的阻塞队列
type BlockQueue[T any] struct {
	items chan T
	once  sync.Once
}

// NewBlockQueue 创建并发安全的阻塞队列
func NewBlockQueue[T any](capacity int) *BlockQueue[T] {
	if capacity <= 0 {
		capacity = 10
	}
	return &BlockQueue[T]{
		items: make(chan T, capacity),
	}
}

// Push 安全入队，队列满时会阻塞
func (q *BlockQueue[T]) Push(item T) {
	q.items <- item
}

// Pop 安全出队，队列空时会阻塞
func (q *BlockQueue[T]) Pop() T {
	item, ok := <-q.items
	if !ok {
		panic("queue is closed")
	}
	return item
}

// Close 关闭队列，使所有阻塞的Pop操作返回
func (q *BlockQueue[T]) Close() {
	q.once.Do(func() {
		close(q.items)
	})
}

// IsEmpty 判断队列是否为空
func (q *BlockQueue[T]) IsEmpty() bool {
	return len(q.items) == 0
}

// IsFull 判断队列是否已满
func (q *BlockQueue[T]) IsFull() bool {
	return len(q.items) == cap(q.items)
}

// Size 获取队列当前元素数量
func (q *BlockQueue[T]) Size() int {
	return len(q.items)
}

// Capacity 获取队列容量
func (q *BlockQueue[T]) Capacity() int {
	return cap(q.items)
}
